from io import BufferedIOBase, TextIOBase
from bcat.stream.streamable import AbstractBinaryReader, AbstractTextReader, AbstractBinaryWriter, AbstractTextWriter


class BinaryReader(AbstractBinaryReader):
    def __init__(self, biobase: BufferedIOBase):
        self.__biobase = biobase

    def readable(self) -> bool:
        return self.__biobase.readable()
    def closed(self) -> bool:
        return self.__biobase.closed
    def close(self) -> bool:
        self.__biobase.close()
        return True
    def read(self, size: int = -1) -> bytes | None:
        b = self.__biobase.read(size)
        return b if len(b) > 0 else None
    def __repr__(self):
        return f"BinaryReader(io:{self.__biobase})"

class TextReader(AbstractTextReader):
    def __init__(self, tiobase: TextIOBase):
        self.__tiobase = tiobase

    def encoding(self) -> str | None:
        self.__tiobase.encoding
    
    def readable(self) -> bool:
        return self.__tiobase.readable()
    def closed(self) -> bool:
        return self.__tiobase.closed
    def close(self) -> bool:
        self.__tiobase.close()
        return True
    def read(self, count: int = -1) -> str | None:
        s = self.__tiobase.read(count)
        return s if len(s) > 0 else None
    def read_line(self, size: int = -1) -> str | None:
        s = self.__tiobase.readline(size)
        return s if len(s) > 0 else None
    def __repr__(self):
        return f"TextReader(io:{self.__tiobase})"

class BinaryWriter(AbstractBinaryWriter):
    def __init__(self, biobase: BufferedIOBase):
        self.__biobase = biobase

    def writable(self) -> bool:
        return self.__biobase.writable()
    def closed(self) -> bool:
        return self.__biobase.closed
    def close(self) -> bool:
        self.__biobase.close()
        return True
    def flush(self) -> bool:
        self.__biobase.flush()
        return True
    def write(self, buffer: bytes) -> int:
        return self.__biobase.write(buffer)
    def __repr__(self):
        return f"BinaryWriter(io:{self.__biobase})"

class TextWriter(AbstractTextWriter):
    def __init__(self, tiobase: TextIOBase):
        self.__tiobase = tiobase

    def encoding(self) -> str | None:
        self.__tiobase.encoding
    
    def writable(self) -> bool:
        return self.__tiobase.writable()
    def closed(self) -> bool:
        return self.__tiobase.closed
    def close(self) -> bool:
        self.__tiobase.close()
        return True
    def write(self, s: str) -> int:
        return self.__tiobase.write(s) 

    def flush(self) -> bool:
        self.__tiobase.flush()
        return True
    def __repr__(self):
        return f"TextWriter(io:{self.__tiobase})"

import unittest 
import io
class TestIOWrapper(unittest.TestCase):
    def test_binary_reader(self):
        src = b"hahahhahaha:\x00\x01"
        reader = BinaryReader(io.BytesIO(src))
        self.assertTrue(reader.readable())
        self.assertFalse(reader.closed())
        self.assertEqual(src, reader.read())
        self.assertIsNone(reader.read())
        self.assertFalse(reader.closed())
        self.assertTrue(reader.close())
        self.assertTrue(reader.closed())

    def test_text_reader(self):
        src = "hahahhahaha:\x00\x01"
        reader = TextReader(io.StringIO(src))
        self.assertTrue(reader.readable())
        self.assertFalse(reader.closed())
        self.assertEqual(src, reader.read())
        self.assertIsNone(reader.read())

    def test_text_reader_line(self):
        src = "hahahhahaha:\n12345\n"
        reader = TextReader(io.StringIO(src))
        self.assertGreater(len(reader.read_line()), 10)
        self.assertGreater(len(reader.read_line()), 5)
        self.assertIsNone(reader.read_line())

    def test_binary_writer(self):
        f = io.BytesIO()
        writer = BinaryWriter(f)
        self.assertFalse(writer.closed())


        self.assertEqual(5, writer.write(b"hello"))
        self.assertEqual(b"hello", f.getbuffer())

        self.assertTrue(writer.flush())

        self.assertTrue(writer.close())
        self.assertTrue(writer.closed())

    def test_text_writer(self):
        f = io.StringIO()
        writer = TextWriter(f)
        self.assertFalse(writer.closed())

        self.assertEqual(5, writer.write('hello'))

        self.assertTrue(writer.flush())
        self.assertTrue(writer.close())
        self.assertTrue(writer.closed())
